//go:build windows
// +build windows

package systemproxy

import (
	"fmt"
	"os/exec"
	"strconv"
	"strings"
	"time"

	"network-firewall-go/internal/types"

	"golang.org/x/sys/windows/registry"
)

// Manager Windows系统代理管理器
type Manager struct {
	originalConfig *types.SystemProxyConfig
}

// NewManager 创建新的系统代理管理器
func NewManager() *Manager {
	return &Manager{}
}

// Enable 启用系统代理
func (m *Manager) Enable(httpPort int) error {
	// 备份原始配置
	if err := m.backupOriginalConfig(); err != nil {
		return fmt.Errorf("备份原始配置失败: %w", err)
	}

	// 设置代理服务器地址
	proxyServer := fmt.Sprintf("127.0.0.1:%d", httpPort)

	// 使用reg命令设置代理（参考nodejs实现）
	if err := m.setProxyWithRegCommand(proxyServer, true); err != nil {
		return fmt.Errorf("设置系统代理失败: %w", err)
	}

	// 刷新系统设置
	if err := m.refreshSystemSettings(); err != nil {
		fmt.Printf("⚠️ 刷新系统设置失败: %v\n", err)
	}

	fmt.Printf("✅ 系统代理已启用: %s\n", proxyServer)
	return nil
}

// Disable 禁用系统代理
func (m *Manager) Disable() error {
	// 恢复原始配置
	if m.originalConfig != nil {
		// 使用reg命令恢复代理设置
		if err := m.setProxyWithRegCommand(m.originalConfig.HTTPProxy, m.originalConfig.ProxyEnable); err != nil {
			// 如果恢复失败，强制禁用代理
			fmt.Printf("⚠️ 恢复原始配置失败，强制禁用代理: %v\n", err)
			if err := m.ForceDisableProxy(); err != nil {
				return fmt.Errorf("强制禁用代理也失败: %w", err)
			}
		}
	} else {
		// 如果没有备份，直接禁用代理
		if err := m.setProxyWithRegCommand("", false); err != nil {
			// 如果禁用失败，强制禁用代理
			fmt.Printf("⚠️ 禁用代理失败，强制禁用: %v\n", err)
			if err := m.ForceDisableProxy(); err != nil {
				return fmt.Errorf("强制禁用代理失败: %w", err)
			}
		}
	}

	// 刷新系统设置
	if err := m.refreshSystemSettings(); err != nil {
		fmt.Printf("⚠️ 刷新系统设置失败: %v\n", err)
	}

	fmt.Println("✅ 系统代理已禁用")
	return nil
}

// ForceDisableProxy 强制禁用系统代理（紧急清理）
func (m *Manager) ForceDisableProxy() error {
	fmt.Println("🚨 执行强制代理清理...")

	regPath := `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`

	// 强制禁用代理
	cmd := exec.Command("reg", "add", regPath, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", "0", "/f")
	if output, err := cmd.CombinedOutput(); err != nil {
		fmt.Printf("⚠️ 强制禁用ProxyEnable失败: %v, 输出: %s\n", err, string(output))
	}

	// 清空代理服务器设置
	cmd = exec.Command("reg", "delete", regPath, "/v", "ProxyServer", "/f")
	if err := cmd.Run(); err != nil {
		// 删除失败不是致命错误，可能本来就不存在
		fmt.Printf("⚠️ 清空ProxyServer失败（可能不存在）: %v\n", err)
	}

	// 清空代理覆盖设置
	cmd = exec.Command("reg", "delete", regPath, "/v", "ProxyOverride", "/f")
	if err := cmd.Run(); err != nil {
		// 删除失败不是致命错误，可能本来就不存在
		fmt.Printf("⚠️ 清空ProxyOverride失败（可能不存在）: %v\n", err)
	}

	// 多次刷新系统设置
	for i := 0; i < 3; i++ {
		m.refreshSystemSettings()
		time.Sleep(500 * time.Millisecond)
	}

	// 额外的刷新方法
	m.notifyProxyChange()

	fmt.Println("✅ 强制代理清理完成")
	return nil
}

// GetCurrentConfig 获取当前代理配置
func (m *Manager) GetCurrentConfig() (*types.SystemProxyConfig, error) {
	key, err := registry.OpenKey(registry.CURRENT_USER,
		`Software\Microsoft\Windows\CurrentVersion\Internet Settings`,
		registry.QUERY_VALUE)
	if err != nil {
		return nil, fmt.Errorf("打开注册表项失败: %w", err)
	}
	defer key.Close()

	config := &types.SystemProxyConfig{}

	// 读取代理启用状态
	if proxyEnable, _, err := key.GetIntegerValue("ProxyEnable"); err == nil {
		config.ProxyEnable = proxyEnable != 0
	}

	// 读取代理服务器
	if proxyServer, _, err := key.GetStringValue("ProxyServer"); err == nil {
		config.HTTPProxy = proxyServer
		config.HTTPSProxy = proxyServer
	}

	// 读取代理绕过列表
	if proxyOverride, _, err := key.GetStringValue("ProxyOverride"); err == nil {
		config.ProxyBypass = proxyOverride
	}

	return config, nil
}

// backupOriginalConfig 备份原始配置
func (m *Manager) backupOriginalConfig() error {
	config, err := m.GetCurrentConfig()
	if err != nil {
		return err
	}

	m.originalConfig = config
	fmt.Printf("📋 已备份原始代理配置: 启用=%v, 服务器=%s\n",
		config.ProxyEnable, config.HTTPProxy)

	return nil
}

// setProxyWithRegCommand 使用reg命令设置代理（参考nodejs实现）
func (m *Manager) setProxyWithRegCommand(proxyServer string, enable bool) error {
	// 设置代理启用状态
	enableValue := "0"
	if enable {
		enableValue = "1"
	}

	// 使用单独的reg命令调用，避免语法问题
	regPath := `HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings`

	// 启用/禁用代理
	cmd := exec.Command("reg", "add", regPath, "/v", "ProxyEnable", "/t", "REG_DWORD", "/d", enableValue, "/f")
	if output, err := cmd.CombinedOutput(); err != nil {
		return fmt.Errorf("设置ProxyEnable失败: %w, 输出: %s", err, string(output))
	}

	// 如果启用代理，设置代理服务器
	if enable && proxyServer != "" {
		// 设置代理服务器
		cmd = exec.Command("reg", "add", regPath, "/v", "ProxyServer", "/t", "REG_SZ", "/d", proxyServer, "/f")
		if output, err := cmd.CombinedOutput(); err != nil {
			return fmt.Errorf("设置ProxyServer失败: %w, 输出: %s", err, string(output))
		}

		// 设置代理覆盖（不代理本地地址）
		proxyOverride := "localhost;localhost:*;127.*;127.0.0.1:*;*.localhost;::1;10.*;172.16.*;172.17.*;172.18.*;172.19.*;172.20.*;172.21.*;172.22.*;172.23.*;172.24.*;172.25.*;172.26.*;172.27.*;172.28.*;172.29.*;172.30.*;172.31.*;192.168.*;<local>"
		cmd = exec.Command("reg", "add", regPath, "/v", "ProxyOverride", "/t", "REG_SZ", "/d", proxyOverride, "/f")
		if output, err := cmd.CombinedOutput(); err != nil {
			return fmt.Errorf("设置ProxyOverride失败: %w, 输出: %s", err, string(output))
		}
	}

	return nil
}

// refreshSystemSettings 刷新系统设置
func (m *Manager) refreshSystemSettings() error {
	// 通知系统代理设置已更改
	// 使用简单的方法通知系统刷新设置
	cmd := exec.Command("rundll32.exe", "wininet.dll,InternetSetOption", "0", "39", "0", "0")
	cmd.Start() // 异步执行，不等待完成

	return nil
}

// notifyProxyChange 通知系统代理设置已更改
func (m *Manager) notifyProxyChange() error {
	// 使用Windows API通知系统设置更改
	// 这比netsh命令更可靠
	cmd := exec.Command("rundll32.exe", "url.dll,FileProtocolHandler", "about:blank")
	cmd.Start() // 不等待完成
	return nil
}

// refreshWinHTTPProxy 刷新WinHTTP代理设置（可选操作）
func (m *Manager) refreshWinHTTPProxy() error {
	// 首先尝试重置WinHTTP代理
	resetCmd := exec.Command("netsh", "winhttp", "reset", "proxy")
	resetCmd.Run() // 忽略错误

	// 然后尝试从IE导入代理设置
	importCmd := exec.Command("netsh", "winhttp", "import", "proxy", "source=ie")
	if err := importCmd.Run(); err != nil {
		return fmt.Errorf("WinHTTP代理导入失败: %w", err)
	}
	return nil
}

// refreshWithNetsh 使用netsh命令刷新（已弃用，保留兼容性）
func (m *Manager) refreshWithNetsh() error {
	cmd := exec.Command("netsh", "winhttp", "import", "proxy", "source=ie")
	if err := cmd.Run(); err != nil {
		return fmt.Errorf("执行netsh命令失败: %w", err)
	}
	return nil
}

// IsEnabled 检查代理是否已启用
func (m *Manager) IsEnabled() bool {
	config, err := m.GetCurrentConfig()
	if err != nil {
		return false
	}
	return config.ProxyEnable
}

// GetProxyServer 获取当前代理服务器
func (m *Manager) GetProxyServer() string {
	config, err := m.GetCurrentConfig()
	if err != nil {
		return ""
	}
	return config.HTTPProxy
}

// InstallCertificate 安装根证书到系统信任存储
func (m *Manager) InstallCertificate(certPath string) error {
	// 使用certlm.msc或certutil命令安装证书
	cmd := exec.Command("certutil", "-addstore", "-user", "Root", certPath)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("安装证书失败: %w, 输出: %s", err, string(output))
	}

	fmt.Printf("✅ 根证书已安装到系统信任存储\n")
	return nil
}

// UninstallCertificate 从系统信任存储卸载根证书
func (m *Manager) UninstallCertificate(certThumbprint string) error {
	// 使用certutil命令删除证书
	cmd := exec.Command("certutil", "-delstore", "-user", "Root", certThumbprint)
	output, err := cmd.CombinedOutput()
	if err != nil {
		return fmt.Errorf("卸载证书失败: %w, 输出: %s", err, string(output))
	}

	fmt.Printf("✅ 根证书已从系统信任存储卸载\n")
	return nil
}

// TestConnectivity 测试代理连通性
func (m *Manager) TestConnectivity(proxyServer string) error {
	// 解析代理服务器地址
	parts := strings.Split(proxyServer, ":")
	if len(parts) != 2 {
		return fmt.Errorf("代理服务器地址格式错误: %s", proxyServer)
	}

	host := parts[0]
	port, err := strconv.Atoi(parts[1])
	if err != nil {
		return fmt.Errorf("代理服务器端口格式错误: %s", parts[1])
	}

	// 使用telnet测试连接
	cmd := exec.Command("telnet", host, strconv.Itoa(port))
	if err := cmd.Start(); err != nil {
		return fmt.Errorf("测试代理连接失败: %w", err)
	}

	// 等待一小段时间然后杀死进程
	go func() {
		cmd.Wait()
	}()

	return nil
}

// GetSystemInfo 获取系统信息
func (m *Manager) GetSystemInfo() map[string]interface{} {
	info := make(map[string]interface{})

	// 获取当前代理配置
	if config, err := m.GetCurrentConfig(); err == nil {
		info["current_proxy"] = config
	}

	// 获取网络接口信息
	cmd := exec.Command("ipconfig", "/all")
	if output, err := cmd.Output(); err == nil {
		info["network_config"] = string(output)
	}

	return info
}
